package cn.px.service.repair.impl;

import cn.px.common.util.*;
import cn.px.dao.enums.*;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageHelper;
import cn.px.common.enums.DataFilterTypeEnum;
import cn.px.common.exception.BusinessException;
import cn.px.common.model.UserInfo;
import cn.px.dao.bean.MyVOPage;
import cn.px.dao.dto.repair.RepairCheckDTO;
import cn.px.dao.dto.repair.RepairFormDTO;
import cn.px.dao.entity.repair.RepairApplicationForm;
import cn.px.dao.entity.repair.RepairCheck;
import cn.px.dao.entity.repair.RepairForm;
import cn.px.dao.mapper.repair.RepairApplicationFormMapper;
import cn.px.dao.mapper.repair.RepairCheckMapper;
import cn.px.dao.mapper.repair.RepairFormMapper;
import cn.px.dao.util.MessageTemplateUtil;
import cn.px.dao.vo.repair.RepairFormVO;
import cn.px.service.base.impl.BaseServiceImpl;
import cn.px.service.event.WorkplaceBacklogEvent;
import cn.px.service.repair.RepairCheckService;
import cn.px.service.repair.RepairFormService;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.weekend.Weekend;
import tk.mybatis.mapper.weekend.WeekendCriteria;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.List;

/**
 * @Description 维修单 service 实现类
 * @author 品讯科技
 * @date 2024-08
 * @Version Copyright (c) 2019,北京乾元坤和科技有限公司 All rights reserved.
 */
@AllArgsConstructor
@Service("repairFormService")
public class RepairFormServiceImpl extends BaseServiceImpl<RepairFormMapper, RepairForm, RepairFormDTO> implements RepairFormService {
    @Resource
    private RepairApplicationFormMapper repairApplicationFormMapper;
    private RepairCheckMapper repairCheckMapper;
    @Resource
    private RepairCheckService repairCheckService;

    @Override
    public int batchDelete(List<String> ids) {
        Weekend<RepairForm> weekend = new Weekend<>(RepairForm.class);
        WeekendCriteria<RepairForm, Object> weekendCriteria = weekend.weekendCriteria();
        weekendCriteria.andIn(RepairForm::getId, ids);
        mapper.deleteByExample(weekend);
        return 1;
    }

    /**
     * 选择登录用户的维修单
     *
     * @param record   :
     * @param pageNum  :
     * @param pageSize :
     * @return
     */
    @Override
    public MyVOPage<RepairFormVO> selectPageVO(RepairFormDTO record, int pageNum, int pageSize) {
        PageHelper.startPage(pageNum, pageSize);
        if( record.getFilter() != null && DataFilterTypeEnum.SELF.getValue() == record.getFilter().intValue()){
            UserInfo userInfo = SecurityUtils.getUserInfo();
            record.setRepairPersonId(userInfo.getUserId());
        }
        return new MyVOPage<>(mapper.selectPageList(record));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void finish(RepairFormDTO dto) {
        // 1. 将维修单的状态修改未待验收
        Weekend<RepairForm> repairFormWeekend = new Weekend<>(RepairForm.class);
        repairFormWeekend.weekendCriteria().andEqualTo(RepairForm::getId, dto.getId());
        RepairForm repairForm = new RepairForm();
        repairForm.setId(dto.getId());
        repairForm.setStatus(RepairFormStatusEnum.NOT_ACCEPTANCE.getValue());
        mapper.updateByExampleSelective(repairForm, repairFormWeekend);
        RepairFormVO repairFormVO = mapper.selectById(repairForm.getId());
        // 2.创建验收单
        RepairCheckDTO repairCheck = new RepairCheckDTO();
        repairCheck.setApplicationId(repairFormVO.getApplicationId());
        repairCheck.setApplicationNo(repairFormVO.getApplicationNo());
        repairCheck.setRepairId(repairFormVO.getId());
        repairCheck.setRepairNo(repairFormVO.getNo());
        repairCheck.setStartTime(LocalDateTime.now());
        repairCheck.setCheckUseId(repairFormVO.getRepairUserId());
        repairCheck.setStatus(RepairCheckStatusEnum.NOT_ACCEPTANCED.getValue());
        RepairCheck check = repairCheckService.saveModelByDTO(repairCheck);
        // 3.更新报修单为待验收
        RepairApplicationForm applicationForm = repairApplicationFormMapper.selectByPrimaryKey(repairFormVO.getApplicationId());
        applicationForm.setStatus(RepairApplicationFormStatusEnum.NOT_ACCEPTANCE.getValue());
        repairApplicationFormMapper.updateByPrimaryKey(applicationForm);
        // 4.发送通知给报修人
        SpringContextHolder.publishEvent(new WorkplaceBacklogEvent( WorkplaceBacklogTypeEnum.REPAIR.getValue(), WorkplaceBacklogDetailTypeEnum.REPAIR_FINISH.getValue(),
                repairCheck.getId(), MessageTemplateUtil.getRepairCheck(check.getId()),
                null, ListUtils.newArrayList(check.getCheckUseId())));

    }

    @Override
    public RepairForm saveByApplication(RepairFormDTO model) {
        Weekend<RepairForm> weekend = new Weekend<>(RepairForm.class);
        weekend.weekendCriteria().andIsNotNull(RepairForm::getId);
        int count = mapper.selectCountByExample(weekend);
        model.setNo(IdGeneratorUtils.getRepairFormNo(++count));
        return super.saveModelByDTO(model);
    }



    @Transactional(rollbackFor = Exception.class)
    @Override
    public RepairForm saveModelByDTO(RepairFormDTO model) {
        Weekend<RepairForm> weekend = new Weekend<>(RepairForm.class);
        weekend.weekendCriteria().andIsNotNull(RepairForm::getId);
        int count = mapper.selectCountByExample(weekend);
        model.setNo(IdGeneratorUtils.getRepairFormNo(++count));
        RepairForm repairForm = super.saveModelByDTO(model);
        // 修改报修单的状态为未分配
        RepairApplicationForm applicationForm = new RepairApplicationForm();
        applicationForm.setId(model.getApplicationId());
        applicationForm.setStatus(RepairApplicationFormStatusEnum.NOT_ALLOCATED.getValue());
        repairApplicationFormMapper.updateByPrimaryKeySelective(applicationForm);
        return repairForm;
    }

    @Override
    public void modModelByDTO(RepairFormDTO model) {
        RepairFormVO entity = mapper.selectById(model.getId());
        if (!RepairFormStatusEnum.YES_DEAL.getValue().equals(entity.getStatus())
                && !RepairFormStatusEnum.RETURN.getValue().equals(entity.getStatus())) {
            throw new BusinessException("该状态不允许编辑");
        }
        RepairForm repairForm = new RepairForm();
        repairForm.setId(model.getId());
        //repairForm.setRepairPersonId(model.getRepairPersonId());
        repairForm.setErrorTypeId(model.getErrorTypeId());
        repairForm.setNeedStop(model.getNeedStop());
        repairForm.setEndTime(LocalDateTime.now());
        repairForm.setTimes((model.getTimes()==null?1:(model.getTimes() + 1)));
        repairForm.setMinutes(model.getMinutes());
        repairForm.setDescripition(model.getDescripition());
        repairForm.setRemark(model.getRemark());
        repairForm.setStatus(RepairFormStatusEnum.NOT_ACCEPTANCE.getValue());
        mapper.updateByPrimaryKeySelective(repairForm);

        // 2.创建验收单,如果已经有则不新建，只要更新
        Weekend<RepairCheck> repairCheckWeekend = new Weekend<>(RepairCheck.class);
        repairCheckWeekend.weekendCriteria().andEqualTo(RepairCheck::getRepairId, model.getId());
        RepairCheck check = repairCheckMapper.selectOneByExample(repairCheckWeekend);
        if(check == null){
            RepairCheckDTO  repairCheck = new RepairCheckDTO();
            repairCheck.setApplicationId(entity.getApplicationId());
            repairCheck.setApplicationNo(entity.getApplicationNo());
            repairCheck.setRepairId(entity.getId());
            repairCheck.setRepairNo(entity.getNo());
            repairCheck.setStartTime(LocalDateTime.now());
            repairCheck.setCheckUseId(entity.getCheckUserId());
            repairCheck.setStatus(RepairCheckStatusEnum.NOT_ACCEPTANCED.getValue());
            check = repairCheckService.saveModelByDTO(repairCheck);
        }else{
            // 返修修改验收单状态为待验收
            check.setStatus(RepairCheckStatusEnum.NOT_ACCEPTANCED.getValue());
            repairCheckMapper.updateByPrimaryKey(check);
        }

        SpringContextHolder.publishEvent(new WorkplaceBacklogEvent( WorkplaceBacklogTypeEnum.REPAIR.getValue(), WorkplaceBacklogDetailTypeEnum.REPAIR_FINISH.getValue(),
                check.getId(), MessageTemplateUtil.getRepairCheck(check.getId()),
                null, ListUtils.newArrayList(check.getCheckUseId())));
    }

    /**
     * 派工，更新维修人的id
     *
     * @param model
     */
    @Override
    public void dispatchModelByDTO(RepairFormDTO model) {
        RepairFormVO entity = mapper.selectById(model.getId());
        if (!RepairFormStatusEnum.YES_DEAL.getValue().equals(entity.getStatus())
                && !RepairFormStatusEnum.NOT_DEAL.getValue().equals(entity.getStatus())) {
            throw new BusinessException("该状态不允许派工");
        }
        RepairForm repairForm = new RepairForm();
        if (StringUtils.isBlank(entity.getDispatchList())){
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("userId", entity.getRepairPersonId());
            jsonObject.put("username", entity.getRepairPersonName());
            jsonObject.put("remark", model.getDispatchRemark());
            jsonObject.put("time", LocalDateTime.now());
            JSONArray jsonArray= new JSONArray();
            jsonArray.add(jsonObject);
            repairForm.setDispatchList(jsonArray.toJSONString());
        }else{
            JSONArray jsonArray= JSONArray.parseArray(entity.getDispatchList() );
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("userId", entity.getRepairPersonId());
            jsonObject.put("username", entity.getRepairPersonName());
            jsonObject.put("remark", model.getDispatchRemark());
            jsonObject.put("time", LocalDateTime.now());
            jsonArray.add(jsonObject);
            repairForm.setDispatchList(jsonArray.toJSONString());
        }
        repairForm.setId(model.getId());
        repairForm.setRepairPersonId(model.getRepairPersonId());
        mapper.updateByPrimaryKeySelective(repairForm);

        SpringContextHolder.publishEvent(new WorkplaceBacklogEvent( WorkplaceBacklogTypeEnum.REPAIR.getValue(), WorkplaceBacklogDetailTypeEnum.REPAIR_DISPATCH.getValue(),
                repairForm.getId(), MessageTemplateUtil.getRepairDispatch(repairForm.getId()),
                null, ListUtils.newArrayList(model.getRepairPersonId())));
    }

    @Override
    public void repairFormDeal(String id) {
        RepairForm repairForm = mapper.selectByPrimaryKey(id);
        if (!RepairFormStatusEnum.NOT_DEAL.getValue().equals(repairForm.getStatus())) {
            throw new BusinessException("该状态不允许接收任务");
        }
        mapper.updateByPrimaryKeySelective(new RepairForm().setId(id)
                .setStartTime(LocalDateTime.now()).setStatus(RepairFormStatusEnum.YES_DEAL.getValue()));
    }

    @Override
    public int countDicitinctSbByTime(RepairFormDTO model) {
        return mapper.countDicitinctSbByTime(model);
    }

    @Override
    public MyVOPage<RepairFormVO> statisticsByGroupBySbPage(RepairFormDTO model, int pageNum, int pageSize) {
        PageHelper.startPage(pageNum, pageSize);
        return new MyVOPage<>(mapper.statisticsByGroupBySb(model));
    }

    @Override
    public MyVOPage<RepairFormVO> statisticsByGroupByMonthPage(RepairFormDTO model, int pageNum, int pageSize) {
        PageHelper.startPage(pageNum, pageSize);
        return new MyVOPage<>(mapper.statisticsByGroupByMonth(model));
    }

    @Override
    public MyVOPage<RepairFormVO> statisticsByGroupByErrorTypePage(RepairFormDTO model, int pageNum, int pageSize) {
        PageHelper.startPage(pageNum, pageSize);
        return new MyVOPage<>(mapper.statisticsByGroupByErrorType(model));
    }

    @Override
    public MyVOPage<RepairFormVO> statisticsByGroupByUserPage(RepairFormDTO model, int pageNum, int pageSize) {
        PageHelper.startPage(pageNum, pageSize);
        return new MyVOPage<>(mapper.statisticsByGroupByUser(model));
    }

    @Override
    public List<RepairFormVO> statisticsResultSbGroupBySbMonth(RepairFormDTO model) {
        return mapper.statisticsResultSbGroupBySbMonth(model);
    }

    @Override
    public List<RepairFormVO> statisticsResultMonthGroupByMonth(RepairFormDTO model) {
        return mapper.statisticsByGroupByMonth(model);
    }

    @Override
    public List<RepairFormVO> statisticsResultErrorTypeByGroupByErrorType(RepairFormDTO model) {
        return mapper.statisticsResultErrorTypeByGroupByErrorType(model);
    }

    @Override
    public List<RepairFormVO> statisticsResultUserByGroupByUser(RepairFormDTO model) {
        return mapper.statisticsResultUserByGroupByUser(model);
    }
}
